package com.comp6231.coordinator;

import java.util.Enumeration;
import java.util.Hashtable;

/**
 * @author Farzana Alam
 * 
 */
public class ElectionSubsystem {
	static private Coordinator localCoordinator;
	static private boolean isLeader = false;

	/**
	 * @param myReplicaID
	 * @param othersReplicaID
	 */
	public ElectionSubsystem(Coordinator localCoordinatorInstance) {
		localCoordinator = localCoordinatorInstance;
		System.out.println("Election sub-system is initiated!");
	}

	/**
	 * This method will be invoked from FailureDetector sub system to initiate
	 * the distributed election
	 * 
	 * @param coordinatorReplicaList
	 * @param myreplicaID
	 * @return
	 */
	static boolean initiateElection(
			Hashtable<String, String[]> coordinatorReplicaList, int myreplicaID) {

		// If this replica is the leader it wont participate in the election and
		// will remain the leader
		if (localCoordinator.isLeader)
			return true;

		System.out.println("\nStarting Election!!");

		/*
		 * Key: Replica Name; Value: [0] => Host Name; [1] => Data UDP Port; [2]
		 * => Control UDP Port;
		 * 
		 * Hashtable will be sent with key as replicaName and values as the
		 * corresponding host names and listening control UDP port. Excluding
		 * myReplicaName it will get only the other replicas' UDP info for the
		 * Hashtable and send myReplicaID to them as UDP packet.
		 * 
		 * Packet Format: "Elect ## myReplicaname ## myReplicaID
		 */
		Enumeration<String> keys = coordinatorReplicaList.keys();
		while (keys.hasMoreElements()) {
			String name = keys.nextElement();
			if (name.equalsIgnoreCase(localCoordinator.myReplicaName)) {
				if (keys.hasMoreElements())
					continue;
				isLeader = true;
				continue;
			}

			String message = "Elect ## " + localCoordinator.myReplicaName
					+ " ## " + myreplicaID;
			ControlUDPClient udpClient = new ControlUDPClient();
			String response = udpClient.sendPacket(
					coordinatorReplicaList.get(name)[0],
					coordinatorReplicaList.get(name)[2], message);
			String reply[] = response.split(" ## ");
			int otherID = Integer.parseInt(reply[2]);

			if (localCoordinator.myReplicaID > otherID) {
				isLeader = false;
				break;
			} else {
				isLeader = true;
			}

		}

		if (isLeader)
			localCoordinator.formLeader(isLeader);
		else
			System.out.println(localCoordinator.myReplicaName
					+ " was not elected as the Leader !!");

		return true;
	}
}
